#ifndef XGINVOKABLE_H
#define XGINVOKABLE_H

class NullClass;

template< typename Ret, typename P1 = NullClass >
class XgInvoke;

/************************************************************************/
/* Interface Invokable (params: 1) Basic Template                       */
/************************************************************************/
template< typename Ret, typename P1 = NullClass >
class XgInvokable
{
public:
	typedef XgInvoke< Ret, P1 > Invoke;

public:
	virtual Ret invoke(P1 a) = 0;

	Invoke* prepare(P1 p1)
	{
		return new Invoke(this, p1);
	}
};

/************************************************************************/
/* Interface Invokable (params: 0)                                      */
/************************************************************************/
template< typename Ret >
class XgInvokable< Ret, NullClass >
{
public:
	typedef XgInvoke< Ret > Invoke;

public:
	virtual Ret invoke() = 0;

	Invoke* prepare()
	{
		return new Invoke(this);
	}
};

/************************************************************************/
/* Class XgInvoke (params: 1) Basic Template                            */
/************************************************************************/
template< typename Ret, typename P1 /*= NullClass*/ >
class XgInvoke
	: public XgInvokable< Ret >
{
public:
	typedef XgInvokable<Ret, P1> Invokable;

public:
	XgInvoke(Invokable* invokable, P1 p1)
		: _invokableIface(invokable), _p1(p1) {};

	Ret invoke()
	{
		_invokableIface->invoke(_p1);
	}

private:
	Invokable* _invokableIface;
	P1 _p1;
};

/************************************************************************/
/* Class XgInvoke (params: 0)                                           */
/************************************************************************/
template< typename Ret >
class XgInvoke< Ret, NullClass >
	: public XgInvokable< Ret >
{
public:
	typedef XgInvokable<Ret> Invokable;

public:
	XgInvoke(Invokable* invokable)
		: _invokableIface(invokable) {};

	Ret invoke()
	{
		_invokableIface->invoke();
	}

private:
	Invokable* _invokableIface;
};

#endif //XGINVOKABLE_H